home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- Smaller Installer © 1996 Bill Goodman, All Rights Reserved
- *******************************************************************************
-
- Alias and Delete Hook Example
-
- This installer hook procedure creates aliases and deletes files. During
- installation, any file or folder whose name ends with "^A", "^D" or "^S" will
- have an alias created for it in the Apple Menu Items, Desktop or Startup folder
- respectively. Any file or folder whose name ends with "^X" will be deleted (no
- file will be installed in its place).
-
- To build this hook procedure, compile this code and create a code resource
- (Type:SICR, ID:501, non-preloaded, nonpurgeable, unlocked, unprotected,
- non-sysheap). Add this resource to the "AliasAndDeleteHook.rsrc" file. Copy all
- the resources in "AliasAndDeleteHook.rsrc" to your installer's resource file.
-
- ******************************************************************************/
-
- // This file is compatible with version 2.1 of the universal headers
- #include <Aliases.h>
- #include <Dialogs.h>
- #include <Finder.h>
- #include <Folders.h>
- #include <GestaltEqu.h>
- #include <Resources.h>
- #include <TextUtils.h>
-
- #ifdef __MWERKS__
- #include <A4Stuff.h>
- #endif
-
- #ifdef THINK_C
- #include <SetUpA4.h>
- #endif
-
- #include "SIHookProc.h"
-
-
- /******************************************************************************
- Function Prototypes
- ******************************************************************************/
- void AfterItemFunction(void);
- void BeforeItemFunction(void);
- OSErr DeleteItem(short delVRefNum, long delDirID, StringPtr delName);
-
-
- /******************************************************************************
- Constant Definitions
- ******************************************************************************/
- // Alert Definitions
- #define aliasAlrt 500 // "An error occurred while creating an alias. Please remove all installed items and try again."
- #define deleteAlrt 501 // "Unable to remove “^0”. Please remove this item and try again."
-
-
- /******************************************************************************
- Variable Definitions
- ******************************************************************************/
- SIHookParmBlk *gParms; // Global pointer to parameter block
- unsigned char gEmptyStr[] = "\p"; // Global empty string
-
-
- /*****************************************************************************/
- pascal void main(
- SIHookParmBlk *parmBlk // Pointer to parameter block
- )
- /******************************************************************************
- This is the main entry point for the installer hook procedure.
- ******************************************************************************/
- {
- #ifdef __MWERKS__
- long holdA4;
- #endif
-
- // Set up access to global variables
- #ifdef THINK_C
- RememberA0();
- SetUpA4();
- #endif
-
- #ifdef __MWERKS__
- holdA4 = SetCurrentA4();
- #endif
-
- gParms = parmBlk;
-
- switch (gParms->function)
- {
- case siHookBeforeItem:
- BeforeItemFunction();
- break;
-
- case siHookAfterItem:
- AfterItemFunction();
- break;
- }
-
- // Restore original A4 value
- #ifdef THINK_C
- RestoreA4();
- #endif
-
- #ifdef __MWERKS__
- SetA4(holdA4);
- #endif
- }
-
-
- /*****************************************************************************/
- void BeforeItemFunction(void)
- /******************************************************************************
- Input parameters:
- "targetVRefNum" Volume reference number of target volume
- "groupAPFlags" Groups currently selected
- "groupQUSel"
- "groupVZSel"
- "group32Flags"
- "group64Flags"
- "group96Flags"
- "groupEnvironFlags"
- "filesRemaining" Number of files remaining to install or remove
- "bytesRemaining" Number of bytes of data remaining to install or remove
- "doingRemove" Non-zero if doing remove operation
- "anyItemsSkipped" Non-zero if any item has been skipped during operation
- "desVRefNum" Volume reference number of destination volume
- "desDirID" Directory ID of destination directory
- "itemName" Name of item to install or remove
- "itemIsFolder" Non-zero if item is a folder
- "fileType" File type (files only)
- "fileCreator" File creator (files only)
- "createDate" Creation date (files only)
- "lastModDate" Last modification date (files only)
- "rsrcForkLen" Length of resource fork (files only)
- "dataForkLen" Length of data fork (files only)
-
- Returns:
- "result" Hook result code (siHookNoErr, siHookQuit, siHookAbort, siHookSkip, siHookItemDone)
- "desDirID" Directory ID of destination directory
- "itemName" Name of item to install or remove
- "itemInfo" Reference passed to AfterItem call
-
- This function is called before each item is installed or removed.
- ******************************************************************************/
- {
- short length;
- unsigned char tag;
-
- gParms->itemInfo = 0; // Clear tag info
-
- // Check item name to see if tag is present
- length = gParms->itemName[0];
- if (length > 2)
- {
- if (gParms->itemName[length - 1] == '^')
- {
- tag = gParms->itemName[length];
- if ((tag == 'A') || (tag == 'D') || (tag == 'S'))
- { // Item has alias tag
- gParms->itemInfo = tag; // Pass tag to AfterItem hook
- gParms->itemName[0] -= 2; // Remove tag so overwrite, create and remove use standard name
- return;
- }
- if (tag == 'X')
- { // Item has delete tag
- if (!gParms->doingRemove)
- { // Only do delete if performing "install" operation
- gParms->itemName[0] -= 2; // Remove tag
- if (DeleteItem(gParms->desVRefNum, gParms->desDirID, gParms->itemName))
- { // Item could not be deleted
- ParamText(gParms->itemName, gEmptyStr, gEmptyStr, gEmptyStr);
- StopAlert(deleteAlrt, NULL);
- gParms->result = siHookQuit; // Force installer to quit
- return;
- }
- }
- gParms->result = siHookItemDone; // Tell installer item has been handled
- return;
- }
- }
- }
- }
-
-
- /*****************************************************************************/
- void AfterItemFunction(void)
- /******************************************************************************
- Input parameters:
- "targetVRefNum" Volume reference number of target volume
- "groupAPFlags" Groups currently selected
- "groupQUSel"
- "groupVZSel"
- "group32Flags"
- "group64Flags"
- "group96Flags"
- "groupEnvironFlags"
- "filesRemaining" Number of files remaining to install or remove
- "bytesRemaining" Number of bytes of data remaining to install or remove
- "doingRemove" Non-zero if doing remove operation
- "anyItemsSkipped" Non-zero if any item has been skipped during operation
- "itemWasSkipped" Non-zero if this item was skipped
- "desVRefNum" Volume reference number of destination volume
- "desDirID" Directory ID of destination directory
- "itemName" Name of item that was installed or removed
- "itemIsFolder" Non-zero if item is a folder
- "fileType" File type (files only)
- "fileCreator" File creator (files only)
- "createDate" Creation date (files only)
- "lastModDate" Last modification date (files only)
- "rsrcForkLen" Length of resource fork (files only)
- "dataForkLen" Length of data fork (files only)
- "itemInfo" Reference passed from BeforeItem call
-
- Returns:
- "result" Hook result code (siHookNoErr, siHookQuit, siHookAbort)
-
- This function is called after each item is installed or removed.
- ******************************************************************************/
- {
- OSErr error;
- long feature;
- OSType folderType;
- Boolean fileCreated = false;
- Boolean fileOpen = false;
- short aliasVRefNum;
- long aliasDirID;
- short aliasResFileNum;
- OSType aliasType;
- OSType aliasCreator;
- AliasHandle aliasHdl;
- FSSpec targFSS;
- FInfo finderInfo;
- CInfoPBRec ib;
-
- if (!gParms->itemInfo)
- return; // No action required unless file was tagged
-
- // No action required if not running System 7.0 or higher
- if (Gestalt(gestaltSystemVersion, &feature))
- return;
- if (feature < 0x0700)
- return;
-
- // Get VRefNum and DirID for alias
- if (gParms->itemInfo == 'A')
- folderType = kAppleMenuFolderType;
- else if (gParms->itemInfo == 'S')
- folderType = kStartupFolderType;
- else // Assume 'D'
- folderType = kDesktopFolderType;
- if (FindFolder(kOnSystemDisk, folderType, kCreateFolder, &aliasVRefNum, &aliasDirID))
- goto Fail;
-
- // Delete alias if doing remove operation
- if (gParms->doingRemove)
- { // Delete alias
- if (DeleteItem(aliasVRefNum, aliasDirID, gParms->itemName))
- { // Item could not be deleted
- ParamText(gParms->itemName, gEmptyStr, gEmptyStr, gEmptyStr);
- StopAlert(deleteAlrt, NULL);
- gParms->result = siHookQuit; // Force installer to quit
- }
- return;
- }
-
- // Create the alias file
- error = HDelete(aliasVRefNum, aliasDirID, gParms->itemName);
- if (error && (error != fnfErr))
- goto Fail;
-
- HCreateResFile(aliasVRefNum, aliasDirID, gParms->itemName);
- if (ResError())
- goto Fail;
- fileCreated = true;
-
- // Open the resource file and add an alias resource
- aliasResFileNum = HOpenResFile(aliasVRefNum, aliasDirID, gParms->itemName, fsRdWrPerm);
- if (aliasResFileNum == -1)
- goto Fail;
- fileOpen = true;
-
- if (FSMakeFSSpec(gParms->desVRefNum, gParms->desDirID, gParms->itemName, &targFSS))
- goto Fail;
-
- if (NewAlias(NULL, &targFSS, &aliasHdl))
- goto Fail;
-
- AddResource((Handle) aliasHdl, 'alis', 0, "\p"); // Create alias resource
- if (ResError())
- goto Fail;
-
- ChangedResource((Handle) aliasHdl);
- if (ResError())
- goto Fail;
-
- WriteResource((Handle) aliasHdl);
- if (ResError())
- goto Fail;
-
- fileOpen = false;
- CloseResFile(aliasResFileNum);
- if (ResError())
- goto Fail;
-
- // Determine the type and creator for the alias based on the type of target
- ib.dirInfo.ioVRefNum = gParms->desVRefNum;
- ib.dirInfo.ioDrDirID = gParms->desDirID;
- ib.dirInfo.ioNamePtr = gParms->itemName;
- ib.dirInfo.ioFVersNum = 0;
- ib.dirInfo.ioFDirIndex = 0;
- if (PBGetCatInfoSync(&ib))
- goto Fail;
-
- if (ib.hFileInfo.ioFlAttrib & ioDirMask)
- { // Item is a folder
- aliasType = kContainerFolderAliasType;
- aliasCreator = 'MACS';
- }
- else
- { // Item is a file
- aliasType = ib.hFileInfo.ioFlFndrInfo.fdType;
- if (aliasType == 'APPL')
- aliasType = kApplicationAliasType; // Use special type for applications
- aliasCreator = ib.hFileInfo.ioFlFndrInfo.fdCreator;
- }
-
- // Set the type and creator of the alias file and set the alias bit in the Finder flags
- if (HGetFInfo(aliasVRefNum, aliasDirID, gParms->itemName, &finderInfo))
- goto Fail;
- finderInfo.fdType = aliasType;
- finderInfo.fdCreator = aliasCreator;
- finderInfo.fdFlags |= kIsAlias;
- if (HSetFInfo(aliasVRefNum, aliasDirID, gParms->itemName, &finderInfo))
- goto Fail;
-
- return; // Good completion
-
- // Error occurred during update
- Fail:
- gParms->result = siHookAbort;
-
- if (fileOpen)
- CloseResFile(aliasResFileNum);
- if (fileCreated)
- HDelete(aliasVRefNum, aliasDirID, gParms->itemName);
- StopAlert(aliasAlrt, NULL);
- }
-
-
- /*****************************************************************************/
- OSErr DeleteItem(
- short delVRefNum, // Volume reference number of item to delete
- long delDirID, // Directory ID of item to delete
- StringPtr delName // Name of item to delete
- )
- /******************************************************************************
- Delete the specified file or folder. Return error code if any error occurs
- (except "File Not Found") which prevents deleting the item.
- ******************************************************************************/
- {
- OSErr error;
- CInfoPBRec ib;
- long saveDirID;
- Str31 name;
- short trashVRefNum;
- long trashDirID;
-
- ib.dirInfo.ioVRefNum = delVRefNum;
- ib.dirInfo.ioDrDirID = delDirID;
- ib.dirInfo.ioNamePtr = delName;
- ib.dirInfo.ioFVersNum = 0;
- ib.dirInfo.ioFDirIndex = 0;
- if (error = PBGetCatInfoSync(&ib))
- {
- if (error == fnfErr)
- error = noErr; // Item does not exist - return no error
- goto Done;
- }
-
- if (ib.hFileInfo.ioFlAttrib & ioDirMask)
- { // Item is a folder - delete all items in folder first
- saveDirID = ib.dirInfo.ioDrDirID;
- ib.dirInfo.ioNamePtr = name;
- ib.dirInfo.ioFDirIndex = 1;
- for (;;)
- {
- ib.dirInfo.ioDrDirID = saveDirID;
- ib.dirInfo.ioFVersNum = 0;
- if (error = PBGetCatInfoSync(&ib))
- {
- if (error == fnfErr)
- break; // End of directory
- goto Done;
- }
- if (DeleteItem(delVRefNum, saveDirID, name))
- ib.dirInfo.ioFDirIndex++; // This delete failed - go to next item
- }
- error = HDelete(delVRefNum, delDirID, delName); // Delete folder
- }
- else
- { // Item is a file
- if (error = HDelete(delVRefNum, delDirID, delName))
- { // Delete failed
- // Try moving file to the trash instead of deleting it (note that this
- // will not work for system software prior to 7.0)
- // Find trash folder
- if (FindFolder(delVRefNum, kTrashFolderType, kCreateFolder, &trashVRefNum, &trashDirID))
- goto Done; // Report error from file delete (this will fail if system software is pre-7.0)
- if (trashVRefNum != delVRefNum)
- goto Done; // Can't move item to trash if not on the same volume
- HDelete(trashVRefNum, trashDirID, delName); // Delete possible duplicate in trash
- if (CatMove(delVRefNum, delDirID, delName, trashDirID, "\p:"))
- goto Done; // Report error from file delete
- error = noErr; // Report no error if file was successfully moved to trash
- }
- }
-
- Done:
- return error;
- }
-